﻿#include"stdafx.h"
#ifdef LK_REFLECTION_
namespace LK
{
	namespace Reflection
	{
		const PDomainNode PLibraryNode::EmptyNode = Convert<PDomainNode,PObject>::RefFrom(PObject());
		PLibraryNode::PLibraryNode(WeakPtr<PTypeLibrary> const& library, PDomainNode const&baseNode, PString const& name)
			:PObject(new LibraryNode(library, baseNode, name)) {}
		PString PLibraryNode::GetName() const
		{
			return Ptr()->GetName();
		}
		PString PLibraryNode::GetFullName()const
		{
			if (GetBaseNode().IsNull())return GetName();
			return GetBaseNode().GetFullName() + GetLibrary().GetSeparatorRef() + GetName();
		}
		void PLibraryNode::Clear()const { Ptr()->Clear(); }

		PDomainNode PLibraryNode::GetBaseNode() const{ return Ptr()->GetBaseNode(); }
		void PLibraryNode::SetName(PString const &name) const{ Ptr()->SetName(name); }
		void PLibraryNode::SetBaseNode(PDomainNode const &node) const{ Ptr()->SetBaseNode(node); }
		WeakPtr<PTypeLibrary>  PLibraryNode::GetLibrary() const
		{
			return Ptr()->GetLibrary();
		}
		void PLibraryNode::SetLibrary(WeakPtr<PTypeLibrary> const&library)const { Ptr()->SetLibrary(library); }

		PString LibraryNode::ToString()const
		{
			return Name;
		}
		void LibraryNode::SetName(PString const&name)
		{
			if (Name != name)
			{
				if (BaseNode.IsNull()) { Name = name; return; }
				Collection::PArray<PLibraryNode>& arr = ((PDomainNode&)BaseNode).GetInnerNodesRef();
				index_t i = arr.IsNull() ? -1 : arr.DichotomyIndexOf(this, &PLibraryNode::Compare);
				Name = name;
				if (i >= 0)//冒泡重排
				{
					while (i > 0 && PLibraryNode::Compare(arr[i - 1], arr[i]) > 0)PObject::SwapReference(arr[i - 1], arr[i]);
					while (i + 1 < arr.GetLength() && PLibraryNode::Compare(arr[i + 1], arr[i]) < 0)PObject::SwapReference(arr[i + 1], arr[i]);
				}
				else ((PDomainNode&)BaseNode).AddInnerNode(this);
			}
		}
		void LibraryNode::SetBaseNode(PDomainNode const&node)
		{
			if (PObject::ReferenceEqual(node, BaseNode))return;
			if (!BaseNode.IsNull())//从原节点移除
			{
				Collection::PArray<PLibraryNode>& arr = ((PDomainNode&)BaseNode).GetInnerNodesRef();
				index_t i = arr.DichotomyIndexOf(this, &PLibraryNode::Compare);
				if (i >= 0 && !arr[i].Equals(this))
				{
					index_t k = 1;
					for (;;)
					{
						if (i - k >= 0 && arr[i - k].Equals(this)) { i -= k; break; }
						if (i + k < arr.GetLength() && arr[i + k].Equals(this)) { i += k; break; }
						if (i - k < 0 && i + k >= arr.GetLength()) { i = -1; break; }
					}
				}
				if (i >= 0)arr.RemoveAt(i);
			}
			BaseNode = node;
			if (!node.IsNull()&& !((PDomainNode&)node).GetInnerNodesRef().IsNull()&& ((PDomainNode&)node).GetInnerNodesRef().DichotomyIndexOf(this, &PLibraryNode::Compare)<0)//插入合适的位置
				((PDomainNode&)node).GetInnerNodesRef().DichotomyInsertAsc(this, &PLibraryNode::Compare);
		}
		LibraryNode::LibraryNode(WeakPtr<PTypeLibrary> const & library, PDomainNode const & baseNode, PString const & name)
			:Name(name), BaseNode(baseNode), Library(){SetLibrary(library);}
		void LibraryNode::Clear()
		{
			Name.SetToNull();
			BaseNode.SetToNull();
			Library.SetToNull();
		}
		WeakPtr<PTypeLibrary> LibraryNode::GetLibrary()const
		{
			return (WeakPtr<PTypeLibrary> &)Library;
		}
		void LibraryNode::SetLibrary(PTypeLibrary const&library)
		{
			Library = library;
		}
		//获取名称
		PString LibraryNode::GetName()const { return Name; }
		PDomainNode LibraryNode::GetBaseNode()const { return (PDomainNode const&)BaseNode; }

		Collection::PArray<PLibraryNode>& PDomainNode::GetInnerNodesRef()const { return Ptr()->InnerNodes; }
		PLibraryNode PDomainNode::GetInnerNodeByName(PString const & str)const { return Ptr()->GetInnerNodeByName(str); }
		void PDomainNode::RemoveInnerNode(PLibraryNode const & node) const
		{
			index_t i = GetInnerNodesRef().IsNull() ? -1 : GetInnerNodesRef().DichotomyIndexOf(node, &PLibraryNode::Compare);
			if (i >= 0)GetInnerNodesRef().RemoveAt(i);
		}
		PLibraryNode PDomainNode::AddInnerNode(PLibraryNode node)const{
			return Ptr()->AddInnerNode(node);
		}
		PDomainNode::PDomainNode(WeakPtr<PTypeLibrary> const& library, PDomainNode const&baseNode, PString const& name) :PLibraryNode(new DomainNode(library, baseNode, name)){}
		DomainNode::DomainNode(WeakPtr<PTypeLibrary> const& library, PDomainNode const&baseNode, PString const& name) : LibraryNode(library, baseNode, name){}
		void DomainNode::Clear()
		{
			if (!InnerNodes.IsNull())for (index_t i = 0; i < InnerNodes.GetLength(); ++i)InnerNodes[i].Clear();
			InnerNodes.SetToNull();
			LibraryNode::Clear();
		}
		/**
		@brief 添加一个内部节点，并返回其引用*/
		PLibraryNode DomainNode::AddInnerNode(PLibraryNode node)
		{
			if (InnerNodes.IsNull())InnerNodes = new LK::Collection::DefaultArray<PLibraryNode>();
			index_t i = InnerNodes.DichotomyIndexOf(node, &PLibraryNode::Compare);
			if (i >= 0)return InnerNodes[i];
			PLibraryNode r =InnerNodes[InnerNodes.DichotomyInsertAsc<PLibraryNode const&>(node, &PLibraryNode::Compare)];
			if (r.GetBaseNode().IsNull())r.SetBaseNode(this);//设置基命名空间
			r.SetLibrary(GetLibrary());//设置库
			return r;
		}
		/**
		@brief 获取当前节点下一个名为str的子节点，如果没有指定名称的子节点，则返回NULL*/
		PLibraryNode DomainNode::GetInnerNodeByName(PString const & str)const
		{
			if (InnerNodes.IsNull())return PLibraryNode();
			index_t i = InnerNodes.DichotomyIndexOf(str, &PLibraryNode::StringCompare);
			return i < 0 ? PLibraryNode() : InnerNodes[i];
		}
	}
}
#endif
